"""新的报告生成器

简单、可靠的数据分析报告生成器
"""

import pandas as pd
import numpy as np
from datetime import datetime
from typing import Dict, Any, List
import logging

class ReportGenerator:
    """报告生成器"""
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
    
    def generate_report(self, data: pd.DataFrame, title: str = "数据分析报告") -> Dict[str, Any]:
        """生成完整的数据分析报告"""
        try:
            # 基础数据分析
            basic_stats = self._analyze_basic_info(data)
            numeric_analysis = self._analyze_numeric_data(data)
            categorical_analysis = self._analyze_categorical_data(data)
            
            # 生成洞察和建议
            insights = self._generate_insights(basic_stats, numeric_analysis, categorical_analysis)
            recommendations = self._generate_recommendations(basic_stats, numeric_analysis, categorical_analysis)
            
            # 构建报告
            report = {
                'title': title,
                'generated_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'summary': {
                    'total_rows': int(data.shape[0]),
                    'total_columns': int(data.shape[1]),
                    'numeric_columns': len(data.select_dtypes(include=[np.number]).columns),
                    'categorical_columns': len(data.select_dtypes(include=['object', 'category']).columns)
                },
                'data_quality': {
                    'missing_values': int(data.isnull().sum().sum()),
                    'missing_percentage': round(float(data.isnull().sum().sum() / (data.shape[0] * data.shape[1]) * 100), 2),
                    'duplicate_rows': int(data.duplicated().sum())
                },
                'numeric_analysis': numeric_analysis,
                'categorical_analysis': categorical_analysis,
                'insights': insights,
                'recommendations': recommendations
            }
            
            return report
            
        except Exception as e:
            self.logger.error(f"报告生成失败: {e}")
            return {
                'title': title,
                'generated_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'error': f"报告生成失败: {str(e)}",
                'summary': {
                    'total_rows': int(data.shape[0]) if hasattr(data, 'shape') else 0,
                    'total_columns': int(data.shape[1]) if hasattr(data, 'shape') else 0
                }
            }
    
    def _analyze_basic_info(self, data: pd.DataFrame) -> Dict[str, Any]:
        """分析基础信息"""
        try:
            return {
                'shape': [int(data.shape[0]), int(data.shape[1])],
                'columns': list(data.columns),
                'dtypes': {col: str(dtype) for col, dtype in data.dtypes.items()},
                'memory_usage': float(data.memory_usage(deep=True).sum() / 1024 / 1024)  # MB
            }
        except Exception as e:
            self.logger.error(f"基础信息分析失败: {e}")
            return {}
    
    def _analyze_numeric_data(self, data: pd.DataFrame) -> Dict[str, Any]:
        """分析数值型数据"""
        try:
            numeric_cols = data.select_dtypes(include=[np.number]).columns
            if len(numeric_cols) == 0:
                return {}
            
            numeric_stats = {}
            for col in numeric_cols:
                try:
                    col_data = data[col].dropna()
                    if len(col_data) > 0:
                        numeric_stats[col] = {
                            'count': int(len(col_data)),
                            'mean': float(col_data.mean()),
                            'median': float(col_data.median()),
                            'std': float(col_data.std()),
                            'min': float(col_data.min()),
                            'max': float(col_data.max()),
                            'q25': float(col_data.quantile(0.25)),
                            'q75': float(col_data.quantile(0.75))
                        }
                except Exception as e:
                    self.logger.warning(f"分析数值列 {col} 失败: {e}")
                    continue
            
            return numeric_stats
            
        except Exception as e:
            self.logger.error(f"数值数据分析失败: {e}")
            return {}
    
    def _analyze_categorical_data(self, data: pd.DataFrame) -> Dict[str, Any]:
        """分析分类型数据"""
        try:
            categorical_cols = data.select_dtypes(include=['object', 'category']).columns
            if len(categorical_cols) == 0:
                return {}
            
            categorical_stats = {}
            for col in categorical_cols:
                try:
                    col_data = data[col].dropna()
                    if len(col_data) > 0:
                        value_counts = col_data.value_counts().head(10)
                        categorical_stats[col] = {
                            'count': int(len(col_data)),
                            'unique_values': int(col_data.nunique()),
                            'most_frequent': str(value_counts.index[0]) if len(value_counts) > 0 else None,
                            'most_frequent_count': int(value_counts.iloc[0]) if len(value_counts) > 0 else 0,
                            'top_values': {str(k): int(v) for k, v in value_counts.items()}
                        }
                except Exception as e:
                    self.logger.warning(f"分析分类列 {col} 失败: {e}")
                    continue
            
            return categorical_stats
            
        except Exception as e:
            self.logger.error(f"分类数据分析失败: {e}")
            return {}
    
    def _generate_insights(self, basic_stats: Dict, numeric_analysis: Dict, categorical_analysis: Dict) -> List[str]:
        """生成数据洞察"""
        insights = []
        
        try:
            # 数据规模洞察
            if 'shape' in basic_stats:
                rows, cols = basic_stats['shape']
                insights.append(f"数据集包含 {rows:,} 行数据和 {cols} 个变量")
            
            # 数据类型洞察
            if numeric_analysis:
                insights.append(f"发现 {len(numeric_analysis)} 个数值型变量，可进行统计分析")
            
            if categorical_analysis:
                insights.append(f"发现 {len(categorical_analysis)} 个分类变量")
            
            # 数值变量特征洞察
            for col, stats in numeric_analysis.items():
                if stats['std'] > 0 and stats['mean'] != 0:
                    cv = stats['std'] / abs(stats['mean'])
                    if cv > 1.5:
                        insights.append(f"变量 '{col}' 显示高度变异性（变异系数: {cv:.2f}）")
            
            # 分类变量特征洞察
            for col, stats in categorical_analysis.items():
                if stats['unique_values'] == 1:
                    insights.append(f"变量 '{col}' 只有一个唯一值，可能需要移除")
                elif stats['unique_values'] > stats['count'] * 0.9:
                    insights.append(f"变量 '{col}' 具有高基数（{stats['unique_values']} 个唯一值）")
            
        except Exception as e:
            self.logger.error(f"生成洞察失败: {e}")
            insights.append("数据分析完成，但生成洞察时遇到问题")
        
        return insights
    
    def _generate_recommendations(self, basic_stats: Dict, numeric_analysis: Dict, categorical_analysis: Dict) -> List[str]:
        """生成分析建议"""
        recommendations = []
        
        try:
            # 基于数据质量的建议
            recommendations.append("建议进行数据清洗，检查异常值和缺失值")
            
            # 基于数值变量的建议
            if numeric_analysis:
                recommendations.append("可以对数值变量进行相关性分析和分布分析")
                
                # 检查是否有需要标准化的变量
                scales_vary = False
                for col, stats in numeric_analysis.items():
                    if abs(stats['max'] - stats['min']) > 1000:
                        scales_vary = True
                        break
                
                if scales_vary:
                    recommendations.append("建议对数值变量进行标准化处理，因为变量间量级差异较大")
            
            # 基于分类变量的建议
            if categorical_analysis:
                recommendations.append("可以对分类变量进行频次分析和交叉表分析")
                
                # 检查高基数变量
                high_cardinality_vars = []
                for col, stats in categorical_analysis.items():
                    if stats['unique_values'] > 20:
                        high_cardinality_vars.append(col)
                
                if high_cardinality_vars:
                    recommendations.append(f"建议对高基数分类变量（{', '.join(high_cardinality_vars[:3])}）进行分组或重新编码")
            
            # 通用分析建议
            recommendations.append("建议进行探索性数据分析（EDA）以发现数据模式")
            recommendations.append("可以考虑进行可视化分析以更好地理解数据分布")
            
        except Exception as e:
            self.logger.error(f"生成建议失败: {e}")
            recommendations.append("建议进行进一步的数据分析")
        
        return recommendations

# 简化的报告生成器（向后兼容）
class SimpleReportGenerator(ReportGenerator):
    """简化的报告生成器（向后兼容）"""
    
    def generate_simple_report(self, data: pd.DataFrame, title: str = "数据分析报告", author: str = "系统生成") -> Dict[str, Any]:
        """生成简化报告（向后兼容方法）"""
        report = self.generate_report(data, title)
        report['author'] = author
        return report